package cn.ahaoweb.drule.core.model.info;

import cn.ahaoweb.drule.core.model.RuleModelConfiguration;
import cn.ahaoweb.drule.core.model.annotations.AttachProperty;
import cn.ahaoweb.drule.core.model.annotations.ClassAnn;
import cn.ahaoweb.drule.core.model.annotations.FieldAnn;
import cn.ahaoweb.drule.core.model.enums.NodeType;
import lombok.ToString;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;

/**
 * @Name: 对象树节点
 * @Description:
 * @Author: wangzhonghao
 * @Date: 2025/1/26 11:47
 */
@ToString
public class TreeNode implements Serializable {

    /**
     * 节点类型
     */
    private NodeType type;

    /**
     * 是否包含规则对象
     * 也就是类型为：{@link NodeType#RULE_OBJECT}, {@link NodeType#LIST_OF_RULE_OBJECT}
     */
    private Boolean containsRuleObject;

    /**
     * 是否是列表（集合）
     */
    private Boolean list;

    /**
     * 子节点集合
     */
    private List<TreeNode> children;

    /**
     * 该节点对应信息
     */
    private BaseInfo info;

    public Boolean isRuleObject() {
        return containsRuleObject;
    }

    public Boolean isList() {
        return list;
    }

    public NodeType getType() {
        return type;
    }

    public List<TreeNode> getChildren() {
        return children;
    }

    public BaseInfo getInfo() {
        return info;
    }

    /**
     * 构建对象结构树
     *
     * @param cl 目标类型
     * @return
     */
    public static TreeNode treeNode(Class<?> cl) {
        return treeNode(cl, "");
    }

    /**
     * 构建对象结构树
     *
     * @param cl 目标类型
     * @return
     */
    public static TreeNode treeNode(Class<?> cl, String prefix) {
        ClassAnn classAnn = cl.getAnnotation(ClassAnn.class);
        if (classAnn == null) {
            throw new NullPointerException(cl + " missing annotation: @ClassAnn();");
        }
        int childDepth = classAnn.childDepth();
        if (childDepth < 0) {
            childDepth = RuleModelConfiguration.getChildDepth();
        }
        return getTreeNode(cl, prefix, childDepth);
    }

    private static TreeNode getTreeNode(Class<?> cl, String prefix, Integer childDepth) {
        TreeNode root = new TreeNode();
        ClassAnn classAnn = cl.getAnnotation(ClassAnn.class);
        if (classAnn != null) {
            Map<String, Field> fieldMap = new HashMap<>();
            Map<String, String> properties = new HashMap<>();
            int superDepth = classAnn.superDepth();
            if (superDepth < 0) {
                // 如果深度不合法，则采用默认配置
                superDepth = RuleModelConfiguration.getSuperDepth();
            }
            // 遍历该类及其父类的字段
            if (superDepth >= 0) {
                int depth = superDepth;
                Class<?> superclass = cl;
                while (depth >= 0 && superclass != null && !Object.class.equals(superclass)) {
                    ClassAnn annotation = superclass.getAnnotation(ClassAnn.class);
                    if (annotation != null) {
                        // 遍历该类型字段
                        for (Field field : superclass.getDeclaredFields()) {
                            if (fieldable(field) && !fieldMap.containsKey(field.getName())) {
                                fieldMap.put(field.getName(), field);
                            }
                        }
                        AttachProperty[] attachProperties = classAnn.properties();
                        if (attachProperties.length > 0) {
                            for (AttachProperty attachProperty : attachProperties) {
                                if (!properties.containsKey(attachProperty.key())) {
                                    properties.put(attachProperty.key(), attachProperty.value());
                                }
                            }
                        }
                        depth--;
                        superclass = superclass.getSuperclass();
                        continue;
                    }
                    depth = -1;
                }
            }
            // 开始赋值
            root.type = NodeType.RULE_OBJECT;
            root.containsRuleObject = true;
            root.list = false;
            String trace = (prefix != null && prefix.trim().length() > 0) ? prefix.trim() : lowerFirst(cl.getSimpleName());
            ClassInfo classInfo = ClassInfo.ClassInfoBuilder
                    .builder()
                    .classType(classAnn.type())
                    .code(lowerFirst(cl.getSimpleName()))
                    .name(classAnn.name())
                    .path(trace)
                    .fqcn(cl.getCanonicalName())
                    .properties(properties)
                    .build();
            root.info = classInfo;
            // 处理字段
            Collection<Field> values = fieldMap.values();
            if (!values.isEmpty()) {
                root.children = new ArrayList<>();
                for (Field field : values) {
                    FieldAnn fieldAnn = field.getAnnotation(FieldAnn.class);
                    NodeType fieldNodeType = NodeType.type(field);
                    // 先配置默认的属性
                    FieldInfo fieldInfo = FieldInfo.FieldInfoBuilder.builder()
                            .name(field.getName())
                            .code(field.getName())
                            .path(trace + "." + field.getName())
                            .fqcn(field.getGenericType().getTypeName().replace("$","."))
                            .build();
                    if (fieldAnn != null) {
                        if (fieldAnn.properties().length > 0) {
                            HashMap<String, String> fieldProp = new HashMap<>();
                            for (AttachProperty property : fieldAnn.properties()) {
                                fieldProp.put(property.key(), property.value());
                            }
                            fieldInfo.setProperties(fieldProp);
                        }
                        fieldInfo.setName(fieldAnn.name());
                        fieldInfo.setDefaultValue(fieldAnn.defaultValue());
                    }
                    TreeNode node = new TreeNode();
                    node.info = fieldInfo;
                    node.type = fieldNodeType;
                    if (fieldNodeType == NodeType.RULE_OBJECT) {
                        if (childDepth > 0) {
                            TreeNode treeNode = getTreeNode(field.getType(), fieldInfo.getPath(), childDepth - 1);
                            node.children = treeNode.getChildren();
                        }
                        node.list = false;
                        node.containsRuleObject = true;
                    } else if (fieldNodeType == NodeType.LIST_OF_RULE_OBJECT) {
                        if (childDepth > 0) {
                            Type genericType = field.getGenericType();
                            ParameterizedTypeImpl ge = null;
                            if (genericType != null && genericType instanceof ParameterizedTypeImpl) {
                                ge = (ParameterizedTypeImpl) genericType;
                            }
                            // 获取带泛型参数的类型
                            Type[] actualTypeArguments = ge.getActualTypeArguments();
                            Class parameterizedType = (Class) actualTypeArguments[0];
                            TreeNode treeNode = getTreeNode(parameterizedType, fieldInfo.getPath(), childDepth - 1);
                            node.children = treeNode.getChildren();
                        }
                        node.list = true;
                        node.containsRuleObject = true;
                    } else {
                        node.list = false;
                        node.containsRuleObject = false;
                    }
                    root.children.add(node);
                }
            }
        } else {
            throw new NullPointerException(cl + " missing annotation: @ClassAnn();");
        }
        return root;
    }

    /**
     * 判断该字段能否作为对象字段
     *
     * @param field
     * @return
     */
    private static boolean fieldable(Field field) {
        int modifiers = field.getModifiers();
        if (!Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers) && !Modifier.isVolatile(modifiers)) {
            FieldAnn annotation = field.getAnnotation(FieldAnn.class);
            return (annotation == null && RuleModelConfiguration.notAnnotatedFieldScanning())
                    || (annotation != null && annotation.enable());
        }
        return false;
    }

    private static String lowerFirst(String s) {
        if (s != null && s.length() > 0) {
            return Character.toLowerCase(s.charAt(0)) + s.substring(1);
        } else {
            return s;
        }
    }

    /**
     * 根据路径定位节点
     *
     * @param path
     * @return
     */
    public TreeNode find(String path) {
        if (path != null) {
            if (path.equals(this.getInfo().getPath())) {
                return this;
            } else if (this.isRuleObject() && path.startsWith(this.getInfo().getPath())) {
                for (TreeNode child : children) {
                    if (child != null) {
                        TreeNode treeNode = child.find(path);
                        if (treeNode != null) {
                            return treeNode;
                        }
                    }
                }
            }
        }
        return null;
    }

}
